ããã¯ã䜿ã£ãReactãšã©ãŒå¢çã®å®è£ æ¹æ³ãåŠã³ããªãœãŒã¹èªã¿èŸŒã¿ãšã©ãŒãé©åã«åŠçãããŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ãšã¢ããªã±ãŒã·ã§ã³ã®å®å®æ§ãåäžãããŸãã
Reactã«ãããå ç¢ãªãªãœãŒã¹ããŒãã£ã³ã°ïŒããã¯ã§ãšã©ãŒå¢çããã¹ã¿ãŒãã
çŸä»£ã®ãŠã§ãã¢ããªã±ãŒã·ã§ã³ã§ã¯ãéåæã§ã®ãªãœãŒã¹èªã¿èŸŒã¿ã¯äžè¬çãªææ³ã§ããAPIããã®ããŒã¿ååŸãç»åã®èªã¿èŸŒã¿ãã¢ãžã¥ãŒã«ã®ã€ã³ããŒããªã©ããªãœãŒã¹èªã¿èŸŒã¿äžã«çºçããããšã©ãŒã®åŠçã¯ãã¹ã ãŒãºãªãŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ã«ãšã£ãŠéåžžã«éèŠã§ããReactã®ãšã©ãŒå¢çã¯ãåã³ã³ããŒãã³ãããªãŒå ã®ã©ãã§çºçããJavaScriptãšã©ãŒã§ããã£ãããããããã®ãšã©ãŒããã°ã«èšé²ããã¢ããªã±ãŒã·ã§ã³å šäœãã¯ã©ãã·ã¥ããã代ããã«ãã©ãŒã«ããã¯UIã衚瀺ããã¡ã«ããºã ãæäŸããŸãããã®èšäºã§ã¯ãReactããã¯ãšçµã¿åãããŠãšã©ãŒå¢çã广çã«äœ¿çšãããªãœãŒã¹èªã¿èŸŒã¿ãšã©ãŒã管çããæ¹æ³ãæ¢ããŸãã
ãšã©ãŒå¢çã®çè§£
React 16以åã¯ãã³ã³ããŒãã³ãã®ã¬ã³ããªã³ã°äžã«æªåŠçã®JavaScriptãšã©ãŒãçºçãããšãReactã®å éšç¶æ ãç Žæãããã®åŸã®ã¬ã³ããªã³ã°ã§äžå¯è§£ãªãšã©ãŒãçºçããããšããããŸããããšã©ãŒå¢çã¯ãåã³ã³ããŒãã³ãã§çºçãããšã©ãŒã®å æ¬çãªãã£ãããããã¯ãšããŠæ©èœããããšã§ããã®åé¡ã«å¯ŸåŠããŸãããããã¯ã以äžã®ã©ã€ããµã€ã¯ã«ã¡ãœããã®ãããããŸãã¯äž¡æ¹ãå®è£ ããReactã³ã³ããŒãã³ãã§ãïŒ
static getDerivedStateFromError(error)ïŒãã®éçã¡ãœããã¯ãåå«ã³ã³ããŒãã³ãã«ãã£ãŠãšã©ãŒãã¹ããŒãããåŸã«åŒã³åºãããŸããã¹ããŒããããšã©ãŒãåŒæ°ãšããŠåãåããã³ã³ããŒãã³ãã®ç¶æ ãæŽæ°ããããã®å€ãè¿ããŸããcomponentDidCatch(error, info)ïŒãã®ã©ã€ããµã€ã¯ã«ã¡ãœããã¯ãåå«ã³ã³ããŒãã³ãã«ãã£ãŠãšã©ãŒãã¹ããŒãããåŸã«åŒã³åºãããŸããã¹ããŒããããšã©ãŒãåŒæ°ãšããŠåãåãã»ããã©ã®ã³ã³ããŒãã³ãããšã©ãŒãã¹ããŒãããã«é¢ããæ å ±ãå«ããªããžã§ã¯ããåãåããŸãããšã©ãŒæ å ±ããã°ã«èšé²ããããã«äœ¿çšã§ããŸãã
éèŠãªç¹ãšããŠããšã©ãŒå¢çã¯ãã¬ã³ããªã³ã°ãã§ãŒãºãã©ã€ããµã€ã¯ã«ã¡ãœãããããã³ãããã®äžã«ããããªãŒå šäœã®ã³ã³ã¹ãã©ã¯ã¿ã§çºçãããšã©ãŒã®ã¿ããã£ããããŸãã以äžã®ãšã©ãŒã¯ãã£ããããŸããïŒ
- ã€ãã³ããã³ãã©ïŒè©³çްã¯ä»¥äžã®ã»ã¯ã·ã§ã³ã§åŠã³ãŸãïŒ
- éåæã³ãŒãïŒäŸïŒ
setTimeoutãrequestAnimationFrameã®ã³ãŒã«ããã¯ïŒ - ãµãŒããŒãµã€ãã¬ã³ããªã³ã°
- ãšã©ãŒå¢çèªäœã§ã¹ããŒããããšã©ãŒïŒãã®åã³ã³ããŒãã³ãã§ã¯ãªãïŒ
ãšã©ãŒå¢çãšReactããã¯ïŒåŒ·åãªçµã¿åãã
åŸæ¥ããšã©ãŒå¢çãå®è£
ããããã«ã¯ã¯ã©ã¹ã³ã³ããŒãã³ãã䜿çšãããŠããŸããããReactããã¯ã¯ããç°¡æœã§é¢æ°çãªã¢ãããŒããæäŸããŸãããšã©ãŒåŠçããžãã¯ãã«ãã»ã«åãããªãœãŒã¹èªã¿èŸŒã¿äžã«ãšã©ãŒãã¹ããŒããå¯èœæ§ã®ããã³ã³ããŒãã³ããã©ãããã䟿å©ãªæ¹æ³ãæäŸãããåå©çšå¯èœãªuseErrorBoundaryããã¯ãäœæã§ããŸãã
ã«ã¹ã¿ã useErrorBoundaryããã¯ã®äœæ
以äžã«useErrorBoundaryããã¯ã®äŸã瀺ããŸãïŒ
import { useState, useCallback } from 'react';
function useErrorBoundary() {
const [error, setError] = useState(null);
const resetError = useCallback(() => {
setError(null);
}, []);
const captureError = useCallback((e) => {
setError(e);
}, []);
const ErrorBoundary = useCallback(({ children, fallback }) => {
if (error) {
return fallback ? fallback : An error occurred: {error.message || String(error)};
}
return children;
}, [error]);
return { ErrorBoundary, captureError, error, resetError };
}
export default useErrorBoundary;
説æïŒ
useStateïŒuseStateã䜿çšããŠãšã©ãŒã®ç¶æ ã管çããŸããåæç¶æ ã§ã¯ãšã©ãŒãnullã«èšå®ããŸããuseCallbackïŒuseCallbackã䜿çšããŠãresetErrorãšcaptureError颿°ãã¡ã¢åããŸãããããã®é¢æ°ããããããšããŠæž¡ãããå ŽåãäžèŠãªåã¬ã³ããªã³ã°ãé²ãããã®è¯ãç¿æ £ã§ããErrorBoundaryã³ã³ããŒãã³ãïŒ ããã¯useCallbackã§äœæããã颿°ã³ã³ããŒãã³ãã§ãchildrenãšãªãã·ã§ã³ã®fallbackãããããåãåããŸããç¶æ ã«ãšã©ãŒãååšããå ŽåãæäŸãããfallbackã³ã³ããŒãã³ããŸãã¯ããã©ã«ãã®ãšã©ãŒã¡ãã»ãŒãžã®ãããããã¬ã³ããªã³ã°ããŸãããã以å€ã®å Žåã¯ãchildrenãã¬ã³ããªã³ã°ããŸãããããç§ãã¡ã®ãšã©ãŒå¢çãšããŠæ©èœããŸããäŸåé å `[error]` ã¯ãerrorã®ç¶æ ãå€åãããšãã«åã¬ã³ããªã³ã°ãããããšãä¿èšŒããŸããcaptureError颿°ïŒ ãã®é¢æ°ã¯ãšã©ãŒç¶æ ãèšå®ããããã«äœ¿çšãããŸãããªãœãŒã¹ãèªã¿èŸŒãéã«try...catchãããã¯å ã§ãããåŒã³åºããŸããresetError颿°ïŒ ãã®é¢æ°ã¯ãšã©ãŒç¶æ ãã¯ãªã¢ããã³ã³ããŒãã³ãããã®childrenãåã¬ã³ããªã³ã°ïŒæœåšçã«ãªãœãŒã¹èªã¿èŸŒã¿ãå詊è¡ïŒã§ããããã«ããŸãã
ãšã©ãŒãã³ããªã³ã°ã䌎ããªãœãŒã¹èªã¿èŸŒã¿ã®å®è£
ã§ã¯ããã®ããã¯ã䜿çšããŠãªãœãŒã¹èªã¿èŸŒã¿ãšã©ãŒãåŠçããæ¹æ³ãèŠãŠã¿ãŸããããAPIãããŠãŒã¶ãŒããŒã¿ãååŸããã³ã³ããŒãã³ããèããŸãïŒ
import React, { useState, useEffect } from 'react';
import useErrorBoundary from './useErrorBoundary';
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
const { ErrorBoundary, captureError, error, resetError } = useErrorBoundary();
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch(`https://api.example.com/users/${userId}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
setUser(data);
} catch (e) {
captureError(e);
}
};
fetchData();
}, [userId, captureError]);
if (error) {
return (
Failed to load user data. {user.name}
Email: {user.email}
{/* Other user details */}説æïŒ
useErrorBoundaryããã¯ãã€ã³ããŒãããŸãã- ããã¯ãåŒã³åºããŠã
ErrorBoundaryã³ã³ããŒãã³ããcaptureError颿°ãerrorç¶æ ãããã³resetError颿°ãååŸããŸãã useEffectããã¯å ã§ãAPIåŒã³åºããtry...catchãããã¯ã§ã©ããããŸãã- APIåŒã³åºãäžã«ãšã©ãŒãçºçããå Žåã
captureError(e)ãåŒã³åºããŠãšã©ãŒç¶æ ãèšå®ããŸãã errorç¶æ ãèšå®ãããŠããå ŽåãErrorBoundaryã³ã³ããŒãã³ããã¬ã³ããªã³ã°ããŸãããšã©ãŒã¡ãã»ãŒãžãšãå詊è¡ããã¿ã³ã衚瀺ããã«ã¹ã¿ã ã®fallbackãããããæäŸããŸãããã¿ã³ãã¯ãªãã¯ãããšresetErrorãåŒã³åºããããšã©ãŒç¶æ ãã¯ãªã¢ãããåã¬ã³ããªã³ã°ãããªã¬ãŒãããŠããŒã¿ã®åååŸã詊ã¿ãããŸãã- ãšã©ãŒãçºçããããŠãŒã¶ãŒããŒã¿ãèªã¿èŸŒãŸããå ŽåããŠãŒã¶ãŒãããã¡ã€ã«ã®è©³çްãã¬ã³ããªã³ã°ããŸãã
ããŸããŸãªçš®é¡ã®ãªãœãŒã¹èªã¿èŸŒã¿ãšã©ãŒã®åŠç
ãªãœãŒã¹èªã¿èŸŒã¿ãšã©ãŒã®çš®é¡ã«ãã£ãŠãç°ãªãåŠçæŠç¥ãå¿ èŠã«ãªãå ŽåããããŸãã以äžã«äžè¬çãªã·ããªãªãšããããžã®å¯ŸåŠæ³ãããã€ã瀺ããŸãïŒ
ãããã¯ãŒã¯ãšã©ãŒ
ãããã¯ãŒã¯ãšã©ãŒã¯ãã¯ã©ã€ã¢ã³ãããµãŒããŒã«æ¥ç¶ã§ããªãå Žåã«çºçããŸãïŒäŸïŒãããã¯ãŒã¯ã®åæ¢ããµãŒããŒã®ããŠã³ã¿ã€ã ïŒãäžèšã®äŸã§ã¯ã`response.ok`ã䜿çšããŠåºæ¬çãªãããã¯ãŒã¯ãšã©ãŒããã§ã«åŠçããŠããŸããããæŽç·Žããããšã©ãŒæ€åºã远å ããããšãã§ããŸããäŸãã°ïŒ
//Inside the fetchData function
try {
const response = await fetch(`https://api.example.com/users/${userId}`);
if (!response.ok) {
// Consider adding specific error code handling
if (response.status === 404) {
throw new Error("User not found");
} else if (response.status >= 500) {
throw new Error("Server error. Please try again later.");
} else {
throw new Error(`HTTP error! status: ${response.status}`);
}
}
const data = await response.json();
setUser(data);
} catch (error) {
if (error.message === 'Failed to fetch') {
// Likely a network error
captureError(new Error('Network error. Please check your internet connection.'));
} else {
captureError(error);
}
}
ãã®å Žåããããã¯ãŒã¯æ¥ç¶ã«åé¡ãããããšã瀺ãã¡ãã»ãŒãžããŠãŒã¶ãŒã«è¡šç€ºããã€ã³ã¿ãŒãããæ¥ç¶ã確èªããããä¿ãããšãã§ããŸãã
APIãšã©ãŒ
APIãšã©ãŒã¯ããµãŒããŒããšã©ãŒã¬ã¹ãã³ã¹ïŒäŸïŒ400 Bad Requestã500 Internal Server ErrorïŒãè¿ãå Žåã«çºçããŸããäžèšã§ç€ºããããã«ã`response.status`ã確èªãããããã®ãšã©ãŒãé©åã«åŠçã§ããŸãã
ããŒã¿è§£æãšã©ãŒ
ããŒã¿è§£æãšã©ãŒã¯ããµãŒããŒããã®ã¬ã¹ãã³ã¹ãæåŸ
ããã圢åŒã§ãªããè§£æã§ããªãå ŽåïŒäŸïŒç¡å¹ãªJSONïŒã«çºçããŸãããããã®ãšã©ãŒã¯ãresponse.json()ã®åŒã³åºããtry...catchãããã¯ã§ã©ããããããšã§åŠçã§ããŸãïŒ
//Inside the fetchData function
try {
const response = await fetch(`https://api.example.com/users/${userId}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
setUser(data);
} catch (error) {
if (error instanceof SyntaxError) {
captureError(new Error('Failed to parse data from server.'));
} else {
captureError(error);
}
}
ç»åèªã¿èŸŒã¿ãšã©ãŒ
ç»åã®èªã¿èŸŒã¿ã«ã¯ã<img>ã¿ã°ã®onErrorã€ãã³ããã³ãã©ã䜿çšã§ããŸãïŒ
function MyImage({ src, alt }) {
const { ErrorBoundary, captureError } = useErrorBoundary();
const [imageLoaded, setImageLoaded] = useState(false);
const handleImageLoad = () => {
setImageLoaded(true);
};
const handleImageError = (e) => {
captureError(new Error(`Failed to load image: ${src}`));
};
return (
Failed to load image.